home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 4 / Amiga Tools 4.iso / tools / netzwerk / parnet-filesystem / netfs.c < prev    next >
C/C++ Source or Header  |  1996-02-26  |  25KB  |  1,104 lines

  1. /*
  2.  * $Id: netfs.c,v 1.3 1995/11/14 00:43:34 Rhialto Exp $
  3.  * $Log: netfs.c,v $
  4.  * Revision 1.3  1995/11/14  00:43:34  Rhialto
  5.  * More casts for yet stricter DICE type checking...
  6.  *
  7.  * Revision 1.2  1995/11/14  00:08:15  Rhialto
  8.  * #ifdef -> #if; cater to stricter compiler.
  9.  *
  10.  * Revision 1.1  1993/12/02  20:45:46  Rhialto
  11.  * Initial revision
  12.  *
  13.  * Actually convert file system actions into network packets.
  14.  * All functions assume that the packet type has been set already,
  15.  * so that the code for some packets can be shared.
  16.  * Read and Write are an exception because they may split the
  17.  * operation in multiple packets.
  18.  */
  19.  
  20. #include "netfs.h"
  21. #include <string.h>
  22.  
  23. #if DEBUG
  24. #   include "syslog.h"
  25. #else
  26. #   define    debug(x)
  27. #endif
  28.  
  29. Prototype Packet      ReqPacket;
  30. Prototype ULONG       Validation;
  31. Prototype ULONG       MyValidation;
  32.  
  33. Packet        ReqPacket;
  34. ULONG        Validation;
  35. ULONG        MyValidation;
  36. NetFileLock    *RootLock;
  37. struct List    NameList;
  38.  
  39. struct Entry {
  40.     struct Node     e_Node;
  41. };
  42.  
  43. /*
  44.  * Remember device parts of names DH0:xx/yy,
  45.  * without the colons.
  46.  */
  47.  
  48. void
  49. AddRemoteName(char *bstr)
  50. {
  51.     struct Entry   *e;
  52.     int         len;
  53.     char       *n;
  54.     static int        nestcount;
  55.  
  56.     debug(("AddRemoteName %d '%.*s'\n", nestcount, bstr[0], bstr+1));
  57.     if (nestcount > 0)
  58.     return;
  59.  
  60.     nestcount++;
  61.  
  62.     n = memchr(bstr + 1, ':', (unsigned char)bstr[0]);
  63.     if (n == NULL) {
  64.     /* Can't happen */
  65.     len = bstr[0];
  66.     } else
  67.     len = n - (bstr + 1);
  68.  
  69.     e = (void *)&NameList;
  70.     while (e = NextNode((struct MinNode *)e)) {
  71.     n = e->e_Node.ln_Name;
  72.  
  73.     if (n[0] == len && strnicmp(n+1, bstr+1, len) == 0) {
  74.         debug(("AddName: Found it\n"));
  75.         goto end;        /* Found it */
  76.     }
  77.     }
  78.  
  79.     debug(("AddName: A new name\n"));
  80.  
  81.     e = dosalloc(sizeof(struct Entry) + 1 + len);
  82.     if (e == NULL)
  83.     goto end;
  84.     n = (char *)(e + 1);
  85.     e->e_Node.ln_Name = n;
  86.     n[0] = len;
  87.     memcpy(n + 1, bstr + 1, len);
  88.  
  89.     AddTail(&NameList, &e->e_Node);
  90.  
  91.     /* Now check if it was a reasonable thing to do... */
  92.     {
  93.     NetFileLock    *nfl;
  94.     static Packet    save;
  95.  
  96.     save = ReqPacket;
  97.     ReqPacket.p_Action = ACTION_LOCATE_OBJECT;
  98.     if (nfl = NetLock(RootLock, n, SHARED_LOCK)) {
  99.         ReqPacket.p_Action = ACTION_FREE_LOCK;
  100.         NetUnLock(nfl);
  101.     } else {
  102.         Remove(e);
  103.         dosfree((void *)e);
  104.     }
  105.     ReqPacket = save;
  106.     }
  107.  
  108. end:
  109.     nestcount--;
  110. }
  111.  
  112. char *
  113. CopyString(char *to, char *from)
  114. {
  115.     int         len = from[0];
  116.  
  117.     debug(("CopyString '%.*s'\n", from[0], from+1));
  118.     memcpy(to, from, 1 + len);
  119.     to = to + 1 + len;
  120.     *to++ = '\0';
  121.     /* Align to longword for conversion to BPTR by the server */
  122.     to = (char *)(((ULONG)to + 3) & ~3);
  123.  
  124.     return to;
  125. }
  126.  
  127. /*
  128.  * Some packets use C style 0-terminated strings.
  129.  * Convert them to counted strings, for consisteny.
  130.  */
  131. char *
  132. CopyCString(char *to, char *from)
  133. {
  134.     int         len = strlen(from);
  135.  
  136.     to[0] = len;
  137.     memcpy(to + 1, from, len);
  138.     to = to + 1 + len;
  139.     *to++ = '\0';
  140.     /* Align to longword for conversion to BPTR by the server */
  141.     to = (char *)(((ULONG)to + 3) & ~3);
  142.  
  143.     return to;
  144. }
  145.  
  146. void *
  147. memchr(const void *cs, int c, size_t n)
  148. {
  149.     while (n > 0) {
  150.     if (*(unsigned char *)cs == (unsigned char)c)
  151.         return cs;
  152.     cs = (char *)cs + 1;
  153.     n--;
  154.     }
  155.     return NULL;
  156. }
  157.  
  158. void
  159. bstrcpy(unsigned char *d, unsigned char *s)
  160. {
  161.     memcpy(d, s, 1 + s[0]);
  162. }
  163.  
  164. int NameIsNetRoot;
  165. int NameIsRemoteDevice;
  166.  
  167. char *
  168. CopyName(char *to, char *from, NetFileLock *parent)
  169. {
  170.     int         len = from[0];
  171.     char       *p;
  172.  
  173.     debug(("CopyName '%.*s'\n", from[0], from+1));
  174.     NameIsNetRoot = 0;
  175.     NameIsRemoteDevice = 0;
  176.     if (p = memchr(from + 1, ':', len)) {
  177.     /* NET:something -> something */
  178.     p++;
  179.     len -= (p - (from + 1));
  180.     to[0] = len;
  181.     if (len)
  182.         memcpy(to + 1, p, len);
  183.     } else
  184.     memcpy(to, from, 1 + len);
  185.     if (parent == RootLock) {
  186.     NameIsNetRoot = (len == 0);
  187.     p = memchr(to + 1, '/', len);
  188.     if (p) {
  189.         /* dh0/something -> dh0:something */
  190.         p[0] = ':';
  191.     } else {
  192.         if (len > 5 && strncmp(&to[1+len-5], ".info", 5) == 0) {
  193.         /* NET:DH0.info -> DH0:Node.rinfo */
  194.         strcpy(&to[1+len-5], ":Node.rinfo");
  195.         len += 6;
  196.         to[0] = len;
  197.         } else {
  198.         /* dh0 -> dh0: */
  199.         to[0] = ++len;
  200.         to[len] = ':';
  201.         NameIsRemoteDevice = 1;
  202.         }
  203.     }
  204.     if (!NameIsNetRoot) {
  205.         AddRemoteName(to);
  206.     }
  207.     }
  208.     to = to + 1 + len;
  209.     *to++ = '\0';
  210.     /* Align to longword for conversion to BPTR by the server */
  211.     to = (char *)(((ULONG)to + 3) & ~3);
  212.  
  213.     return to;
  214. }
  215.  
  216. NetFileLock *
  217. ValidLock(NetFileLock *netfl)
  218. {
  219.     if (netfl == NULL)
  220.     return RootLock;
  221.  
  222.     if (netfl->nfl_Validation == Validation)
  223.     return netfl;
  224.  
  225.     if (netfl->nfl_Validation == 0)
  226.     return netfl;
  227.  
  228.     error = ERROR_DEVICE_NOT_MOUNTED;
  229.     return NULL;
  230. }
  231.  
  232. int
  233. ValidFile(NetFileHandle *netfh)
  234. {
  235.     return netfh && netfh->nfh_Validation == Validation;
  236. }
  237.  
  238. NetFileLock *
  239. MakeNetLock(ULONG fl)
  240. {
  241.     NetFileLock *netfl;
  242.  
  243.     if (netfl = AllocMem(sizeof(*netfl), MEMF_PUBLIC|MEMF_CLEAR)) {
  244.     netfl->nfl_FileLock = fl;
  245.     netfl->nfl_Validation = Validation;
  246.     }
  247. #if DEBUG
  248.     debug(("MakeNetLock %x from %x\n", netfl, fl));
  249.     if (fl == 0)
  250.     debug(("!!! 0 remote lock !!!\n"));
  251. #endif
  252.     return netfl;
  253. }
  254.  
  255. void
  256. FreeNetLock(NetFileLock *netfl)
  257. {
  258.     if (netfl && netfl != RootLock)
  259.     FreeMem(netfl, sizeof(*netfl));
  260. }
  261.  
  262. NetFileHandle *
  263. MakeNetFile(ULONG fh)
  264. {
  265.     NetFileHandle *netfh;
  266.  
  267.     if (netfh = AllocMem(sizeof(*netfh), MEMF_PUBLIC|MEMF_CLEAR)) {
  268.     netfh->nfh_FileHandle = fh;
  269.     netfh->nfh_Validation = Validation;
  270.     }
  271.     debug(("MakeNetFile %x\n", netfh));
  272.     return netfh;
  273. }
  274.  
  275. void
  276. FreeNetFile(NetFileHandle *netfh)
  277. {
  278.     if (netfh)
  279.     FreeMem(netfh, sizeof(*netfh));
  280. }
  281.  
  282. /* ---------------------------------------------------------------------- */
  283.  
  284. Prototype NetFileLock *NetLock(NetFileLock *parent, char *name, ULONG mode);
  285.  
  286. NetFileLock *
  287. NetLock(NetFileLock *parent, char *name, ULONG mode)
  288. {
  289.     char       *end;
  290.  
  291.     if (parent = ValidLock(parent)) {
  292.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  293.     ReqPacket.p_Arg[1] = mode;
  294.     end = CopyName((char *)&ReqPacket.p_Arg[2], name, parent);
  295.  
  296.     debug(("NetLock: %x %s %d\n", parent, (char *)&ReqPacket.p_Arg[2]+1,
  297.         mode));
  298.  
  299.     if (NameIsNetRoot)
  300.         return RootLock;
  301.  
  302.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  303.         error = ReqPacket.p_Res2;
  304.         if (ReqPacket.p_Res1) {
  305.         return MakeNetLock(ReqPacket.p_Res1);
  306.         }
  307.     }
  308.     }
  309.     return NULL;
  310. }
  311.  
  312. Prototype void NetUnLock(NetFileLock *netfl);
  313.  
  314. void
  315. NetUnLock(NetFileLock *netfl)
  316. {
  317.     if (netfl) {
  318.     if ((netfl = ValidLock(netfl))) {
  319.         if (netfl == RootLock)
  320.         return;
  321.  
  322.         ReqPacket.p_Arg[0] = netfl->nfl_FileLock;
  323.  
  324.         (void)SendRecv(&ReqPacket, REQSIZE(1), &ReqPacket, STDREPLY);
  325.     }
  326.     FreeNetLock(netfl);
  327.     }
  328. }
  329.  
  330. Prototype NetFileLock *NetDupLock(NetFileLock *netfl);
  331.  
  332. NetFileLock *
  333. NetDupLock(NetFileLock *netfl)
  334. {
  335.     if (netfl = ValidLock(netfl)) {
  336.     if (netfl == RootLock)
  337.         return RootLock;
  338.  
  339.     ReqPacket.p_Arg[0] = netfl->nfl_FileLock;
  340.  
  341.     if (SendRecv(&ReqPacket, REQSIZE(1), &ReqPacket, STDREPLY) == 0) {
  342.         error = ReqPacket.p_Res2;
  343.         if (ReqPacket.p_Res1) {
  344.         return MakeNetLock(ReqPacket.p_Res1);
  345.         }
  346.     }
  347.     }
  348.     return NULL;
  349. }
  350.  
  351. Prototype NetFileLock *NetCreateDir(NetFileLock *parent, char *name);
  352.  
  353. NetFileLock *
  354. NetCreateDir(NetFileLock *parent, char *name)
  355. {
  356.     char       *end;
  357.  
  358.     if (parent = ValidLock(parent)) {
  359.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  360.     end = CopyName((char *)&ReqPacket.p_Arg[1], name, parent);
  361.  
  362.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  363.         error = ReqPacket.p_Res2;
  364.         if (ReqPacket.p_Res1) {
  365.         return MakeNetLock(ReqPacket.p_Res1);
  366.         }
  367.     }
  368.     }
  369.     return NULL;
  370. }
  371.  
  372. Prototype ULONG NetDeleteFile(NetFileLock *parent, char *name);
  373.  
  374. ULONG
  375. NetDeleteFile(NetFileLock *parent, char *name)
  376. {
  377.     char       *end;
  378.  
  379.     if (parent = ValidLock(parent)) {
  380.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  381.     end = CopyName((char *)&ReqPacket.p_Arg[1], name, parent);
  382.  
  383.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  384.         error = ReqPacket.p_Res2;
  385.         return ReqPacket.p_Res1;
  386.     }
  387.     }
  388.     return DOSFALSE;
  389. }
  390.  
  391. Prototype NetFileLock *NetParentDir(NetFileLock *netfl);
  392.  
  393. NetFileLock *
  394. NetParentDir(NetFileLock *netfl)
  395. {
  396.     if (netfl == NULL) {
  397.     error = ERROR_OBJECT_NOT_FOUND;
  398.     } else if (netfl = ValidLock(netfl)) {
  399.     if (netfl == RootLock)
  400.         return NULL;
  401.  
  402.     ReqPacket.p_Arg[0] = netfl->nfl_FileLock;
  403.  
  404.     if (SendRecv(&ReqPacket, REQSIZE(1), &ReqPacket, STDREPLY) == 0) {
  405.         error = ReqPacket.p_Res2;
  406.         if (ReqPacket.p_Res1)
  407.         return MakeNetLock(ReqPacket.p_Res1);
  408.         else if (error == 0)
  409.         return RootLock;
  410.     }
  411.     }
  412.     return NULL;
  413. }
  414.  
  415. Prototype ULONG NetSameLock(NetFileLock *lock1, NetFileLock *lock2);
  416.  
  417. ULONG
  418. NetSameLock(NetFileLock *lock1, NetFileLock *lock2)
  419. {
  420.     if ((lock1 = ValidLock(lock1)) && (lock2 = ValidLock(lock2))) {
  421.     if (lock1 == lock2) {
  422.         debug(("NetSameLock: same local ptr %x\n", lock1));
  423.         return DOSTRUE;
  424.     }
  425.  
  426. #if 1
  427.     if (lock1 == RootLock || lock2 == RootLock) {
  428.         /*error = ERROR_DEVICE_NOT_MOUNTED;*/
  429.         error = ERROR_INVALID_LOCK;
  430.         return DOSFALSE;
  431.     }
  432. #endif
  433.  
  434.     if (lock1->nfl_FileLock == lock2->nfl_FileLock) {
  435.         debug(("NetSameLock: same remote ptr %x\n", lock1->nfl_FileLock));
  436.         return DOSTRUE;
  437.     }
  438.  
  439.     debug(("NetSameLock: compare remote %x %x\n", lock1->nfl_FileLock, lock2->nfl_FileLock));
  440.     ReqPacket.p_Arg[0] = lock1->nfl_FileLock;
  441.     ReqPacket.p_Arg[1] = lock2->nfl_FileLock;
  442.  
  443.     if (SendRecv(&ReqPacket, REQSIZE(2), &ReqPacket, STDREPLY) == 0) {
  444.         error = ReqPacket.p_Res2;
  445.         return ReqPacket.p_Res1;
  446.     }
  447.     }
  448.     return DOSFALSE;
  449. }
  450.  
  451. ULONG
  452. NetRelabel(NetFileLock *slock, char *sname, NetFileLock *dlock, char *dname)
  453. {
  454.  
  455.     char       *end;
  456.     char       *colon;
  457.  
  458.     ReqPacket.p_Action = ACTION_RENAME_DISK;
  459.     end = CopyName((char *)&ReqPacket.p_Arg[0], sname, slock);
  460.     colon = end;
  461.     end = CopyName((char *)end,                 dname, dlock);
  462.  
  463.     /* Remove colon from new name */
  464.     if (colon[colon[0]] == ':') {
  465.     colon[colon[0]] = '\0';
  466.     colon[0]--;
  467.     }
  468.  
  469.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  470.     error = ReqPacket.p_Res2;
  471.     return ReqPacket.p_Res1;
  472.     }
  473. }
  474.  
  475. Prototype ULONG NetRename(NetFileLock *slock, char *sname, NetFileLock *dlock, char *dname);
  476.  
  477. ULONG
  478. NetRename(NetFileLock *slock, char *sname, NetFileLock *dlock, char *dname)
  479. {
  480.     char       *end;
  481.     char        root;
  482.     char        dev;
  483.  
  484.     if ((slock = ValidLock(slock)) && (dlock = ValidLock(dlock))) {
  485.     ReqPacket.p_Arg[0] = slock->nfl_FileLock;
  486.     ReqPacket.p_Arg[1] = dlock->nfl_FileLock;
  487.     end = CopyName((char *)&ReqPacket.p_Arg[2], sname, slock);
  488.     root = NameIsNetRoot;
  489.     dev  = NameIsRemoteDevice;
  490.     end = CopyName((char *)end,                 dname, dlock);
  491.     root += NameIsNetRoot;
  492.     dev  += NameIsRemoteDevice;
  493.  
  494.     if (dev == 2)
  495.         return NetRelabel(slock, sname, dlock, dname);
  496.     if (root || dev) {
  497.         error = ERROR_RENAME_ACROSS_DEVICES;
  498.         return DOSFALSE;
  499.     }
  500.  
  501.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  502.         error = ReqPacket.p_Res2;
  503.         return ReqPacket.p_Res1;
  504.     }
  505.     }
  506.     return DOSFALSE;
  507. }
  508.  
  509. Prototype ULONG NetSetProtect(NetFileLock *parent, char *name, ULONG protect);
  510.  
  511. ULONG
  512. NetSetProtect(NetFileLock *parent, char *name, ULONG protect)
  513. {
  514.     char       *end;
  515.  
  516.     if (parent = ValidLock(parent)) {
  517.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  518.     ReqPacket.p_Arg[1] = protect;
  519.     end = CopyName((char *)&ReqPacket.p_Arg[2], name, parent);
  520.  
  521.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  522.         error = ReqPacket.p_Res2;
  523.         return ReqPacket.p_Res1;
  524.     }
  525.     }
  526.     return DOSFALSE;
  527. }
  528.  
  529. Prototype ULONG NetExamine(NetFileLock *netfl, struct FileInfoBlock *fib);
  530.  
  531. ULONG
  532. NetExamine(NetFileLock *netfl, struct FileInfoBlock *fib)
  533. {
  534.     if (netfl = ValidLock(netfl)) {
  535.     if (netfl == RootLock) {
  536.         char       *p;
  537.  
  538.         memset(fib, 0, sizeof(*fib));
  539.         /* Includes fib_DiskKey = 0 */
  540.         fib->fib_DirEntryType =
  541.         fib->fib_EntryType = ST_ROOT;
  542.         p = BTOC(VolNode->dl_Name);
  543.         bstrcpy(&fib->fib_FileName[0], p);
  544.         fib->fib_Date = VolNode->dl_VolumeDate;
  545.  
  546.         return DOSTRUE;
  547.     }
  548.  
  549.     ReqPacket.p_Arg[0] = netfl->nfl_FileLock;
  550.  
  551.     if (SendRecv2(&ReqPacket, REQSIZE(1), NULL, 0,
  552.               &ReqPacket, STDREPLY, fib, sizeof(*fib)) == 0) {
  553. #if DEBUG
  554.     {
  555.         debug(("key %x size %d name '%.*s'\n", fib->fib_DiskKey, fib->fib_Size,
  556.             fib->fib_FileName[0], &fib->fib_FileName[1]));
  557.     }
  558. #endif
  559.         error = ReqPacket.p_Res2;
  560.         return ReqPacket.p_Res1;
  561.     }
  562.     }
  563.     return DOSFALSE;
  564. }
  565.  
  566. Prototype ULONG NetExNext(NetFileLock *netfl, struct FileInfoBlock *fib);
  567.  
  568. /*
  569.  * For ExNext, (a part of) the FileInfoBlock must be sent
  570.  * with the request. To be flexible, here is a define for
  571.  * how much we actually transmit. In this case, everything
  572.  * up to the end of the file name plus a bit of slop to
  573.  * survive round-down errors.
  574.  * See also notes in the server.
  575.  */
  576.  
  577. #define EXNEXTFIBSIZE(f) (offsetof(struct FileInfoBlock, fib_FileName[0]) + \
  578.               f->fib_FileName[0] + 2)
  579.  
  580. ULONG
  581. NetExNext(NetFileLock *netfl, struct FileInfoBlock *fib)
  582. {
  583.     if (netfl = ValidLock(netfl)) {
  584.     if (netfl == RootLock) {
  585.         struct Entry   *e;
  586.         int         i;
  587.  
  588.         if (fib->fib_DiskKey > 0 && fib->fib_DirEntryType == ST_USERDIR) {
  589.         fib->fib_DirEntryType =
  590.         fib->fib_EntryType = ST_FILE;
  591.         i = fib->fib_FileName[0];
  592.         strcpy(&fib->fib_FileName[1+i], ".info");
  593.         fib->fib_FileName[0] = i + 5;
  594.  
  595.         return DOSTRUE;
  596.         }
  597.  
  598.         e = NextNode((struct MinNode *)&NameList);
  599.         for (i = fib->fib_DiskKey; e && i > 0; i--)
  600.         e = NextNode((struct MinNode *)e);
  601.  
  602.         if (e) {
  603.         fib->fib_DiskKey++;
  604.         fib->fib_DirEntryType =
  605.         fib->fib_EntryType = ST_USERDIR;
  606.         bstrcpy(&fib->fib_FileName[0], e->e_Node.ln_Name);
  607.  
  608.         return DOSTRUE;
  609.         }
  610.  
  611.         error = ERROR_NO_MORE_ENTRIES;
  612.         return DOSFALSE;
  613.     }
  614.  
  615.     ReqPacket.p_Arg[0] = netfl->nfl_FileLock;
  616.  
  617.     if (SendRecv2(&ReqPacket, REQSIZE(1), fib, EXNEXTFIBSIZE(fib),
  618.               &ReqPacket, STDREPLY, fib, sizeof(*fib)) == 0) {
  619.         error = ReqPacket.p_Res2;
  620.         return ReqPacket.p_Res1;
  621.     }
  622.     }
  623.     return DOSFALSE;
  624. }
  625. Prototype ULONG NetDiskInfo(struct InfoData *id);
  626.  
  627. ULONG
  628. NetDiskInfo(struct InfoData *id)
  629. {
  630.     memset(id, 0, sizeof(*id));
  631.     id->id_DiskState = ID_VALIDATED;
  632.     id->id_NumBlocks = 1;
  633.     id->id_NumBlocksUsed = 1;
  634.     id->id_BytesPerBlock = MAXDATA;
  635.     id->id_DiskType = ID_DOS_DISK;
  636.     id->id_VolumeNode = CTOB(VolNode);
  637.     id->id_InUse = 1;
  638.  
  639.     return DOSTRUE;
  640. }
  641.  
  642. Prototype ULONG NetInfo(NetFileLock *netfl, struct InfoData *id);
  643.  
  644. ULONG
  645. NetInfo(NetFileLock *netfl, struct InfoData *id)
  646. {
  647.     if (netfl == RootLock)
  648.     return NetDiskInfo(id);
  649.  
  650.     if (netfl = ValidLock(netfl)) {
  651.     ReqPacket.p_Arg[0] = netfl->nfl_FileLock;
  652.  
  653.     if (SendRecv2(&ReqPacket, REQSIZE(1), NULL, 0,
  654.               &ReqPacket, STDREPLY, id, sizeof(*id)) == 0) {
  655.         id->id_VolumeNode = 0;
  656.         error = ReqPacket.p_Res2;
  657.         return ReqPacket.p_Res1;
  658.     }
  659.     }
  660.     return DOSFALSE;
  661. }
  662.  
  663. Prototype ULONG NetSetComment(NetFileLock *parent, char *name, char *comment);
  664.  
  665. ULONG
  666. NetSetComment(NetFileLock *parent, char *name, char *comment)
  667. {
  668.     char       *end;
  669.  
  670.     if (parent = ValidLock(parent)) {
  671.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  672.     end = CopyName((char *)&ReqPacket.p_Arg[1], name, parent);
  673.     end = CopyString(end,               comment);
  674.  
  675.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  676.         error = ReqPacket.p_Res2;
  677.         return ReqPacket.p_Res1;
  678.     }
  679.     }
  680.     return DOSFALSE;
  681. }
  682.  
  683. Prototype ULONG NetSetDate(NetFileLock *parent, char *name, struct DateStamp *ds);
  684.  
  685. ULONG
  686. NetSetDate(NetFileLock *parent, char *name, struct DateStamp *ds)
  687. {
  688.     char       *end;
  689.  
  690.     if (parent = ValidLock(parent)) {
  691.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  692.     ReqPacket.p_Arg[1] = ds->ds_Days;
  693.     ReqPacket.p_Arg[2] = ds->ds_Minute;
  694.     ReqPacket.p_Arg[3] = ds->ds_Tick;
  695.     end = CopyName((char *)&ReqPacket.p_Arg[4], name, parent);
  696.  
  697.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  698.         error = ReqPacket.p_Res2;
  699.         return ReqPacket.p_Res1;
  700.     }
  701.     }
  702.     return DOSFALSE;
  703. }
  704.  
  705. Prototype NetFileHandle *NetOpen(NetFileLock *parent, char *name, ULONG mode);
  706.  
  707. NetFileHandle *
  708. NetOpen(NetFileLock *parent, char *name, ULONG mode)
  709. {
  710.     char       *end;
  711.  
  712.     if (parent = ValidLock(parent)) {
  713.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  714.     end = CopyName((char *)&ReqPacket.p_Arg[1], name, parent);
  715.     /* mode is actually the packet type */
  716.  
  717.     debug(("NetOpen: %x %s %d\n", parent, (char *)&ReqPacket.p_Arg[1]+1,
  718.         mode));
  719.  
  720.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  721.         error = ReqPacket.p_Res2;
  722.         if (ReqPacket.p_Res1) {
  723.         return MakeNetFile(ReqPacket.p_Res1);
  724.         }
  725.     }
  726.     }
  727.     return NULL;
  728. }
  729.  
  730. Prototype LONG NetRead(NetFileHandle *netfh, char *buffer, LONG length);
  731.  
  732. LONG
  733. NetRead(NetFileHandle *netfh, char *buffer, LONG length)
  734. {
  735.     LONG        done = 0;
  736.  
  737.     if (ValidFile(netfh)) {
  738.     while (length > 0) {
  739.         ReqPacket.p_Action = ACTION_READ;
  740.         ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  741.         ReqPacket.p_Arg[1] = min(length, MAXDATA);
  742.  
  743.         if (SendRecv2(&ReqPacket, REQSIZE(2), NULL, 0,
  744.               &ReqPacket, STDREPLY, buffer, ReqPacket.p_Arg[1]) != 0)
  745.         break;
  746.  
  747.         if ((long)ReqPacket.p_Res1 <= 0)
  748.         break;
  749.  
  750.         length -= ReqPacket.p_Res1;
  751.         buffer += ReqPacket.p_Res1;
  752.         done   += ReqPacket.p_Res1;
  753.     }
  754.  
  755.     error = ReqPacket.p_Res2;
  756.     return done;
  757.     }
  758.  
  759.     return -1;
  760. }
  761.  
  762. Prototype LONG NetWrite(NetFileHandle *netfh, char *buffer, LONG length);
  763.  
  764. LONG
  765. NetWrite(NetFileHandle *netfh, char *buffer, LONG length)
  766. {
  767.     LONG        done = 0;
  768.  
  769.     if (ValidFile(netfh)) {
  770.     while (length > 0) {
  771.         LONG        thislength = min(length, MAXDATA);
  772.  
  773.         ReqPacket.p_Action = ACTION_WRITE;
  774.         ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  775.         ReqPacket.p_Arg[1] = thislength;
  776.  
  777.         if (SendRecv2(&ReqPacket, REQSIZE(2), buffer, thislength,
  778.               &ReqPacket, STDREPLY, NULL, 0) != 0)
  779.         break;
  780.  
  781.         if (ReqPacket.p_Res1 == -1)
  782.         break;
  783.  
  784.         done   += ReqPacket.p_Res1;
  785.  
  786.         if (ReqPacket.p_Res1 != thislength)
  787.         break;
  788.  
  789.         length -= ReqPacket.p_Res1;
  790.         buffer += ReqPacket.p_Res1;
  791.     }
  792.  
  793.     error = ReqPacket.p_Res2;
  794.     return done;
  795.     }
  796.  
  797.     return -1;
  798. }
  799.  
  800. Prototype ULONG NetClose(NetFileHandle *netfh);
  801.  
  802. ULONG
  803. NetClose(NetFileHandle *netfh)
  804. {
  805.     if (ValidFile(netfh)) {
  806.     ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  807.  
  808.     if (SendRecv(&ReqPacket, REQSIZE(1), &ReqPacket, STDREPLY) == 0) {
  809.         if (ReqPacket.p_Res1 && (error = ReqPacket.p_Res2) == 0) {
  810.         FreeNetFile(netfh);
  811.         }
  812.         return ReqPacket.p_Res1;
  813.     }
  814.     }
  815.     return DOSFALSE;
  816. }
  817.  
  818. Prototype ULONG NetSeek(NetFileHandle *netfh, ULONG position, ULONG mode);
  819.  
  820. ULONG
  821. NetSeek(NetFileHandle *netfh, ULONG position, ULONG mode)
  822. {
  823.     if (ValidFile(netfh)) {
  824.     ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  825.     ReqPacket.p_Arg[1] = position;
  826.     ReqPacket.p_Arg[2] = mode;
  827.  
  828.     if (SendRecv(&ReqPacket, REQSIZE(3), &ReqPacket, STDREPLY) == 0) {
  829.         error = ReqPacket.p_Res2;
  830.         return ReqPacket.p_Res1;
  831.     }
  832.     }
  833.     return DOSFALSE;
  834. }
  835.  
  836. /*
  837.  * Target can be eith
  838.  */
  839.  
  840. Prototype ULONG NetMakeLink(NetFileLock *parent, char *name, void *target, ULONG mode);
  841.  
  842. ULONG
  843. NetMakeLink(NetFileLock *parent, char *name, void *target, ULONG soft)
  844. {
  845.     char       *end;
  846.  
  847.     if (parent = ValidLock(parent)) {
  848.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  849.     ReqPacket.p_Arg[1] = soft;
  850.     if (soft) {
  851.         /* XXX Is this a BCPL or C string? */
  852.         end = CopyCString((char *)&ReqPacket.p_Arg[2], target);
  853.     } else {
  854.         NetFileLock *tlock = ValidLock((NetFileLock *)target);
  855.  
  856.         debug(("MakeLink hard %s -> %x\n", name, target));
  857.         if (tlock == 0) {
  858.         error = ERROR_INVALID_LOCK;
  859.         return DOSFALSE;
  860.         }
  861.         ReqPacket.p_Arg[2] = tlock->nfl_FileLock;
  862.         end = (char *)&ReqPacket.p_Arg[3];
  863.     }
  864.     end = CopyName(end, name, parent);
  865.  
  866.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  867.         error = ReqPacket.p_Res2;
  868.         return ReqPacket.p_Res1;
  869.     }
  870.     }
  871.     return NULL;
  872. }
  873.  
  874. Prototype ULONG NetReadLink(NetFileLock *parent, char *name, char *target, ULONG length);
  875.  
  876. ULONG
  877. NetReadLink(NetFileLock *parent, char *name, char *target, ULONG length)
  878. {
  879.     char       *end;
  880.  
  881.     if (parent = ValidLock(parent)) {
  882.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  883.     ReqPacket.p_Arg[1] = length;
  884.     end = CopyCString((char *)&ReqPacket.p_Arg[2], name);   /* XXX should be CopyCName */
  885.  
  886.     if (SendRecv2(&ReqPacket, end - &ReqPacket, NULL, 0,
  887.               &ReqPacket, STDREPLY, target, length) == 0) {
  888.         error = ReqPacket.p_Res2;
  889.         return ReqPacket.p_Res1;
  890.     }
  891.     }
  892.     return NULL;
  893. }
  894. Prototype ULONG NetSetFileSize(NetFileHandle *netfh, ULONG position, ULONG mode);
  895.  
  896. ULONG
  897. NetSetFileSize(NetFileHandle *netfh, ULONG position, ULONG mode)
  898. {
  899.     /* Same arguments and result */
  900.     return NetSeek(netfh, position, mode);
  901. }
  902.  
  903. Prototype NetFileHandle *NetOpenFromLock(NetFileLock *parent);
  904.  
  905. NetFileHandle *
  906. NetOpenFromLock(NetFileLock *parent)
  907. {
  908.     if (parent = ValidLock(parent)) {
  909.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  910.  
  911.     if (SendRecv(&ReqPacket, REQSIZE(1), &ReqPacket, STDREPLY) == 0) {
  912.         error = ReqPacket.p_Res2;
  913.         if (ReqPacket.p_Res1) {
  914.         return MakeNetFile(ReqPacket.p_Res1);
  915.         }
  916.     }
  917.     }
  918.     return NULL;
  919. }
  920.  
  921. Prototype NetFileLock *NetParentOfFH(NetFileHandle *netfh);
  922.  
  923. NetFileLock *
  924. NetParentOfFH(NetFileHandle *netfh)
  925. {
  926.     if (ValidFile(netfh)) {
  927.     ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  928.  
  929.     if (SendRecv(&ReqPacket, REQSIZE(1), &ReqPacket, STDREPLY) == 0) {
  930.         error = ReqPacket.p_Res2;
  931.         if (ReqPacket.p_Res1) {
  932.         return MakeNetLock(ReqPacket.p_Res1);
  933.         }
  934.     }
  935.     }
  936.     return NULL;
  937. }
  938.  
  939. Prototype ULONG NetChangeMode(ULONG type, void *object, ULONG mode);
  940.  
  941. ULONG
  942. NetChangeMode(ULONG type, void *object, ULONG mode)
  943. {
  944.     ULONG        object2 = 0;
  945.  
  946.     switch (type) {
  947.     case CHANGE_FH:
  948.     if (object = ValidLock(object))
  949.         object2 = ((NetFileHandle *)object)->nfh_FileHandle;
  950.     break;
  951.     case CHANGE_LOCK:
  952.     if (ValidFile(object))
  953.         object2 = ((NetFileLock *)object)->nfl_FileLock;
  954.     break;
  955.     }
  956.     if (object2) {
  957.     ReqPacket.p_Arg[0] = type;
  958.     ReqPacket.p_Arg[1] = object2;
  959.     ReqPacket.p_Arg[2] = mode;
  960.  
  961.     if (SendRecv(&ReqPacket, REQSIZE(3), &ReqPacket, STDREPLY) == 0) {
  962.         error = ReqPacket.p_Res2;
  963.         return ReqPacket.p_Res1;
  964.     }
  965.     }
  966.  
  967.     error = ERROR_OBJECT_WRONG_TYPE;
  968.     return DOSFALSE;
  969.  
  970. }
  971.  
  972. Prototype NetFileLock *NetDupLockFromFH(NetFileHandle *netfh);
  973.  
  974. NetFileLock *
  975. NetDupLockFromFH(NetFileHandle *netfh)
  976. {
  977.     return NetParentOfFH(netfh);
  978. }
  979.  
  980. Prototype ULONG NetExamineFH(NetFileHandle *netfh, struct FileInfoBlock *fib);
  981.  
  982. ULONG
  983. NetExamineFH(NetFileHandle *netfh, struct FileInfoBlock *fib)
  984. {
  985.     if (ValidFile(netfh)) {
  986.     ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  987.  
  988.     if (SendRecv2(&ReqPacket, REQSIZE(1), NULL, 0,
  989.               &ReqPacket, STDREPLY, fib, sizeof(*fib)) == 0) {
  990.         error = ReqPacket.p_Res2;
  991.         return ReqPacket.p_Res1;
  992.     }
  993.     }
  994.     return DOSFALSE;
  995. }
  996.  
  997. void
  998. NetLockRecordReply(struct DosPacket *dp, ULONG res1, ULONG res2)
  999. {
  1000.     debug(("NetLockRecordReply %x %x\n", res1, res2));
  1001.  
  1002.     dp->dp_Res1 = res1;
  1003.     dp->dp_Res2 = res2;
  1004.     returnpacket(dp);
  1005. }
  1006.  
  1007. Prototype void NetLockRecord(struct DosPacket *dp, NetFileHandle *netfh, LONG start, LONG length, LONG mode, LONG timeout);
  1008.  
  1009. void
  1010. NetLockRecord(struct DosPacket *dp, NetFileHandle *netfh, LONG start,
  1011.           LONG length, LONG mode, LONG timeout)
  1012. {
  1013.     debug(("NetLockRecord %x %x->%x\n", dp, netfh, netfh->nfh_FileHandle));
  1014.  
  1015.     if (ValidFile(netfh)) {
  1016.     ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  1017.     ReqPacket.p_Arg[1] = start;
  1018.     ReqPacket.p_Arg[2] = length;
  1019.     ReqPacket.p_Arg[3] = mode;
  1020.     ReqPacket.p_Arg[4] = timeout;
  1021.     ReqPacket.p_Arg[5] = (ULONG)dp;        /* extra */
  1022.  
  1023.     if (Send2(&ReqPacket, REQSIZE(6), NULL, 0) != 0) {
  1024.         NetLockRecordReply(dp, DOSFALSE, ERROR_NO_FREE_STORE);
  1025.     }
  1026.     } else {
  1027.     debug(("Bad NetFH\n"));
  1028.     NetLockRecordReply(dp, DOSFALSE, ERROR_OBJECT_WRONG_TYPE);
  1029.     }
  1030. }
  1031.  
  1032. Prototype ULONG NetFreeRecord(NetFileHandle *netfh, LONG start, LONG length);
  1033.  
  1034. ULONG
  1035. NetFreeRecord(NetFileHandle *netfh, LONG start, LONG length)
  1036. {
  1037.     if (ValidFile(netfh)) {
  1038.     ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  1039.     ReqPacket.p_Arg[1] = start;
  1040.     ReqPacket.p_Arg[2] = length;
  1041.  
  1042.     if (SendRecv(&ReqPacket, REQSIZE(3), &ReqPacket, STDREPLY) == 0) {
  1043.         error = ReqPacket.p_Res2;
  1044.         return ReqPacket.p_Res1;
  1045.     }
  1046.     }
  1047.     return NULL;
  1048. }
  1049.  
  1050. /* ---------------------------------------------------------------------- */
  1051.  
  1052. Prototype void DoAsyncReply(Packet *pkt);
  1053.  
  1054. void
  1055. DoAsyncReply(Packet *pkt)
  1056. {
  1057.     debug(("DoAsyncReply\n"));
  1058.  
  1059.     switch (pkt->p_Data[0]) {
  1060.     case ACTION_LOCK_RECORD:
  1061.     NetLockRecordReply((void *)pkt->p_Data[1], pkt->p_Res1, pkt->p_Res2);
  1062.     break;
  1063.     default:
  1064.     debug(("Weird AsyncReply, %d\n", pkt->p_Data[0]));
  1065.     }
  1066. }
  1067.  
  1068. /* ---------------------------------------------------------------------- */
  1069.  
  1070. Prototype ULONG OpenNetFS(void);
  1071.  
  1072. ULONG
  1073. OpenNetFS(void)
  1074. {
  1075.     ULONG        error;
  1076.  
  1077.     debug(("OpenNetFS\n"));
  1078.     error = OpenNetwork();
  1079.     if (error == 0) {
  1080.     RootLock = MakeNetLock(0);
  1081.     RootLock->nfl_Validation = 0;
  1082.     NewList(&NameList);
  1083.     }
  1084.     debug(("OpenNetFS done\n"));
  1085.     return error;
  1086. }
  1087.  
  1088. Prototype ULONG CloseNetFS(void);
  1089.  
  1090. ULONG
  1091. CloseNetFS(void)
  1092. {
  1093.     NetFileLock *nfl;
  1094.  
  1095.     debug(("CloseNetFS\n"));
  1096.     CloseNetwork();
  1097.  
  1098.     nfl = RootLock;
  1099.     RootLock = NULL;
  1100.     FreeNetLock(nfl);
  1101.  
  1102.     return 0;
  1103. }
  1104.